package com.feng.cloud.auth.service.impl;

import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.feng.cloud.auth.properties.FengAuthProperties;
import com.feng.cloud.auth.service.ValidateCodeService;
import com.feng.cloud.common.constants.SystemConstant;
import com.feng.cloud.common.constants.request.RequestParamsConstant;
import com.feng.cloud.common.exception.auth.AuthStatus;
import com.feng.cloud.common.exception.auth.ValidateCodeException;
import com.feng.cloud.common.service.RedisService;
import com.wf.captcha.GifCaptcha;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @ClassName ValidateCodeService
 * @Description TODO
 * @Author Better Feng
 * @Date 2019/12/16 13:43
 * @Version 1.0
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class ValidateCodeServiceImpl implements ValidateCodeService {

    // redis服务
    private final RedisService redisService;
    // 授权相关配置
    private final FengAuthProperties authProperties;
    private final CaptchaService captchaService;


    @Override
    public void create(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String key = request.getParameter(RequestParamsConstant.VALIDATE_CODE_KEY);
        if (StringUtils.isBlank(key)) {
            throw new ValidateCodeException(AuthStatus.VALIDATE_CODE_KEY_EMPTY);
        }
        setHeader(response, authProperties.getCode().getType());

        Captcha captcha = createCaptcha();
        redisService.set(SystemConstant.CODE_PREFIX + key, StringUtils.lowerCase(captcha.text()), authProperties.getCode().getTime());
        captcha.out(response.getOutputStream());
    }

    @Override
    public void captchaVerification(String captchaVerification) {
        if (StringUtils.isBlank(captchaVerification)) {
            throw new ValidateCodeException(AuthStatus.CAPTCHA_VERIFICATION_CODE_EMPTY);
        }
        CaptchaVO captchaVO = new CaptchaVO();
        captchaVO.setCaptchaVerification(captchaVerification);
        ResponseModel response = captchaService.verification(captchaVO);
        if(!response.isSuccess()){
            log.error("滑动验证码失败:{}", response);
            throw new ValidateCodeException(AuthStatus.VALIDATE_CODE_ERROR);
        }
    }

    @Override
    public void check(String key, String value) {
        if (StringUtils.isBlank(key)) {
            throw new ValidateCodeException(AuthStatus.VALIDATE_CODE_KEY_EMPTY);
        }
        if (StringUtils.isBlank(value)) {
            throw new ValidateCodeException(AuthStatus.VALIDATE_CODE_VALUE_EMPTY);
        }
        if (authProperties.getCode().getLength() != value.length()) {
            throw new ValidateCodeException(AuthStatus.VALIDATE_CODE_ERROR);
        }
        String redisKey = SystemConstant.CODE_PREFIX + key;
        Object codeInRedis = redisService.get(redisKey);
        if (codeInRedis == null) {
            throw new ValidateCodeException(AuthStatus.VALIDATE_CODE_INVALID);
        }
        if (!StringUtils.equalsIgnoreCase(value, String.valueOf(codeInRedis))) {
            throw new ValidateCodeException(AuthStatus.VALIDATE_CODE_ERROR);
        } else {
            // 移除验证码
            redisService.del(redisKey);
        }
    }

    private Captcha createCaptcha() {
        Captcha captcha = null;
        if (StringUtils.equalsIgnoreCase(authProperties.getCode().getType(), "gif")) {
            captcha = new GifCaptcha(authProperties.getCode().getWidth(), authProperties.getCode().getHeight(), authProperties.getCode().getLength());
        } else {
            captcha = new SpecCaptcha(authProperties.getCode().getWidth(), authProperties.getCode().getHeight(), authProperties.getCode().getLength());
        }
        captcha.setCharType(authProperties.getCode().getCharType());
        return captcha;
    }

    private void setHeader(HttpServletResponse response, String type) {
        if (StringUtils.equalsIgnoreCase(type, "gif")) {
            response.setContentType(MediaType.IMAGE_GIF_VALUE);
        } else {
            response.setContentType(MediaType.IMAGE_PNG_VALUE);
        }
        response.setHeader(HttpHeaders.PRAGMA, "No-cache");
        response.setHeader(HttpHeaders.CACHE_CONTROL, "No-cache");
        response.setDateHeader(HttpHeaders.EXPIRES, 0L);
    }
}
